`

基于BitSet的广告索引检索引擎实现

阅读更多

 

 编写不易,转载请注明 (http://shihlei.iteye.com/blog/2358063)

 

一 概述

广告系统中,广告活动创建时,运营人员通常会根据广告的受众情况,设置广告的基本定向,如香奈儿推广 需要投放上海的女士用户。

 

因此,根据定象条件对广告活动进行索引和检索是投放引擎的必备功能。

 

通常实现可以使用ElasticSearch这样的索引引擎。本文尝试实现一个简单的基于BitMap的内存索引和检索引擎。       

 

二 思路

索引:为每个定向条件构建一个BitSet,在该定向条件创建索引,相当于将BitSet 的 广告活动ID位 置1;

检索:提供定向集合,取出指定定向的BitSet,BitSet之间通过“与”运算,取交集获得最终的BitSet,获取最终BitSet中位为1 的下标即满足条件的bitmap。

 

优点:内存索引且内存空间很小。

缺点:

1)当BitSet位数很大时,进行&运算会比较慢,待进一步研究。

2)广告活动ID 必须为 整型。

3)定向条件很多的情况,感觉使用还是有些困难。

4)定向条件之间会有“或”运算的情况,这里没有考虑。

        其他没有深想。

 

三 实现

public class AdvEngine {

    private static final int BITSET_SIZE = 100000000;

    //索引列表
    private Map<TargetEnum, BitSet> indexes = new HashMap<>();


    public static void main(String[] args) {
        AdvEngine advEngine = new AdvEngine();

        //广告1000 投放:北京,女
        advEngine.index(1000, Arrays.asList(TargetEnum.GENDER_FEMALE, TargetEnum.AREA_BEIJING));
        //广告2000 投放:上海,女
        advEngine.index(2000, Arrays.asList(TargetEnum.GENDER_FEMALE, TargetEnum.AREA_SHAGNHAI));
        //广告3000 投放:女
        advEngine.index(3000, Arrays.asList(TargetEnum.GENDER_FEMALE));
        //广告4000 投放:上海 ,男
        advEngine.index(4000, Arrays.asList(TargetEnum.GENDER_MALE, TargetEnum.AREA_SHAGNHAI));

        System.out.println("上海,女 可投放广告:");
        List<Integer> campaingIds = advEngine.search(Arrays.asList(TargetEnum.GENDER_FEMALE, TargetEnum.AREA_SHAGNHAI));
        campaingIds.stream().forEach(System.out::println);

        System.out.println("女 可投放广告:");
        campaingIds = advEngine.search(Arrays.asList(TargetEnum.GENDER_FEMALE));
        campaingIds.stream().forEach(System.out::println);
    }


    /**
     * 创建索引
     *
     * @param campaignId 广告id
     * @param targets    定向类型
     */
    public void index(int campaignId, List<TargetEnum> targets) {
        for (TargetEnum target : targets) {
            BitSet bitSet = indexes.get(target);
            if (bitSet == null) {
                bitSet = new BitSet(BITSET_SIZE);
                indexes.put(target, bitSet);
            }
            bitSet.set(campaignId, true);
        }
    }


    /**
     * 查找符合类型的广告活动
     *
     * @param targets 定向类型
     */
    public List<Integer> search(List<TargetEnum> targets) {
        List<Integer> campaignIds = new LinkedList<>();
        if (targets.isEmpty()) {
            return campaignIds;
        }

        BitSet finalSet = null;

        //取出满足所有定向条件的集合
        long start = System.nanoTime();
        for (TargetEnum target : targets) {
            BitSet campaingBitSet = indexes.get(target);
            if (campaingBitSet == null) {
                break;
            }
            if (finalSet == null) {
                finalSet = (BitSet) campaingBitSet.clone();
            } else {
                finalSet.and(campaingBitSet);
            }
        }
        long end = System.nanoTime();
        System.out.println("time1 : " + (end - start));
        if (finalSet == null) {
            return campaignIds;
        }

        long start2 = System.nanoTime();
        for (int i = 0; i < finalSet.length(); i++) {
            if (!finalSet.get(i)) {
                continue;
            }
            campaignIds.add(i);
        }
        long end2 = System.nanoTime();
        System.out.println("time2 : " + (end2-start2));

        return campaignIds;
    }

    /**
     * 删除索引
     *
     * @param campaingId 广告ID
     */
    public void dropIndex(int campaingId) {
        //取出满足所有定向条件的集合
        for (BitSet campaingBitSet : indexes.values()) {
            campaingBitSet.clear(campaingId);
        }
    }


    /**
     * 定向类型枚举
     */
    public static enum TargetEnum {
        //性别定向
        GENDER_MALE,
        GENDER_FEMALE,
        //地域定向
        AREA_BEIJING,
        AREA_SHAGNHAI;
    }

}

 

四 BitSet说明

(1)设置位

void set(int bitIndex)

 

(2)获取位

boolean get(int bitIndex)

 

(3)操作

void and(BitSet set) //与

void or(BitSet set)  //或

void xor(BitSet set) //异或

 

(4)清除位

void clear(int bitIndex)

0
0
分享到:
评论
4 楼 ShihLei 2017-04-24  
wsnbmw 写道
改为if (campaingBitSet == null) {
finalSet=null;
break;
}


是,不满某个定向条件,直接退出
3 楼 wsnbmw 2017-04-19  
改为if (campaingBitSet == null) {
finalSet=null;
break;
}
2 楼 wsnbmw 2017-04-19  
if (campaingBitSet == null) {
finalSet=null;
continue;
}
1 楼 wsnbmw 2017-04-19  
    List<Integer> campaingIds = advEngine.search(Arrays.asList(TargetEnum.GENDER_FEMALE, TargetEnum.AREA_SHAGNHAI)); 如果换成其它城市就有bug,无法使用

相关推荐

    Go-bitset-Go包实现bitsets

    - 在数据库索引中,位集可以用来高效地存储和检索数据。 - 在图论中,位集可以用来标记节点的属性。 - 在压缩算法中,位集可以用来记录数据的编码状态。 7. **与其他数据结构的比较** - 相比于数组或列表,位集...

    Java 项目-搜索引擎的设计与实现.zip

    搜索引擎是一个复杂的信息检索系统,它能够收集、索引、存储和检索网络上的大量数据,以满足用户的查询需求。这个Java项目旨在实现一个基本的搜索引擎,让我们逐一解析其中涉及的关键技术和知识点。 1. **全文搜索*...

    Java编程中的HashSet和BitSet详解

    BitSet的实现基于位数组(Bit Array),因此它可以非常高效地存储和检索数据。 那么,为什么Apache Commons作者选择使用BitSet代替HashSet呢?主要原因是BitSet占用更少的内存,速度也更快。HashSet需要存储每个...

    lucene索引结构原理

    Lucene是Apache软件基金会的开放源代码全文搜索引擎库,它为Java开发人员提供了强大的文本搜索功能。理解Lucene的索引结构原理对于优化搜索性能和设计高效的搜索应用至关重要。 首先,我们要知道Lucene的索引并非...

    LUCENE索引搜索数据库技术汇总

    - **Solr和Elasticsearch**: 当索引过大时,可以使用基于Lucene的分布式搜索引擎如Solr或Elasticsearch,它们提供了更高级的集群管理、复制、负载均衡等功能。 6. **Lucene与数据库结合** - **数据库集成**: 通过...

    基于lucene的开发JavaEE项目

    7. **分布式搜索**:对于大型JavaEE项目,单台服务器可能无法满足性能需求,这时我们可以采用Solr或Elasticsearch等基于Lucene的分布式搜索引擎,实现横向扩展和负载均衡。 8. **整合到JavaEE框架**:将Lucene集成...

    搜索引擎Lucene_资料

    - **倒排索引优化**: 如位图过滤(Bitset Filter)和DocValues,可以减少搜索过程中的I/O操作。 总结来说,Lucene是一个强大且灵活的全文搜索引擎库,其核心在于高效的索引和搜索机制。通过熟练掌握Lucene,开发者...

    lucene 2.3

    例如,知名的Wikipedia搜索引擎就曾基于Lucene构建,展示了其在大规模数据检索中的强大能力。 总结,Lucene 2.3版本是Java平台上实现高速中文检索的利器,它不仅提供了完善的中文支持,还在索引构建、搜索操作、...

    lucene 全文检索

    它提供了索引和搜索文本数据的强大功能,广泛应用于各种应用程序,如内容管理系统、搜索引擎以及任何需要快速查找大量文本数据的场景。Lucene 的核心特性包括分词、索引构建、查询解析和高效的搜索算法。 ### 一、...

    luke-Lucene 7.1.0

    例如,通过改进的位集(BitSet)实现,可以更快地进行文档过滤操作。此外, postings format 的改进使得存储更高效,减少了磁盘空间占用。 2. **查询性能**:在查询处理方面,Lucene 7.1.0增强了对复杂查询的处理...

    Lucene 原理 介绍

    Lucene是Apache软件基金会的一个开源项目,它是一个强大的全文搜索引擎库,完全用Java编写,可以被嵌入到各种应用程序中,提供高效、可扩展的全文检索功能。Lucene的核心机制是基于倒排索引,这是一种为了快速进行...

    基于lucene3.0 书籍查询系统

    在3.0版本中,Lucene提供了强大的文本分析、索引和搜索功能,使得开发者能够快速地构建自己的全文检索应用。本系统就是基于Lucene 3.0版本构建的一个书籍查询系统,主要目标是帮助用户快速、准确地在大量书籍数据中...

    Lucene.Net.dll

    Lucene.Net.dll是基于Java版本的Lucene移植到.NET Framework上的开源库,它实现了全文检索、索引和搜索等功能,支持多种语言,包括中文。2.9.2版本是该库的一个稳定版本,具备良好的兼容性和性能优化,广泛应用于...

    INVERTED_INDEX:倒排索引结构的实现,用C++编写

    倒排索引是一种高效的数据结构,常用于全文搜索引擎和数据库系统中,用于快速定位文档或数据行中包含特定关键词的位置。在本项目“INVERTED_INDEX”中,开发者Nick Georgiadis使用C++实现了这一重要概念。下面我们将...

    javabitset源码-montysolr:Solr天体物理数据系统

    在标题提及的 "javabitset源码-montysolr:Solr天体物理数据系统" 中,我们可以推测这个项目可能是在Solr(一个流行的全文搜索引擎)中使用BitSet来处理天体物理数据。下面我们将深入探讨Java BitSet以及它如何应用于...

    Lucene 3.0 原理与代码分析

    通过对《Lucene 3.0 原理与代码分析》的学习,开发者可以深入了解全文检索的实现细节,从而更好地利用Lucene构建高效、定制化的搜索解决方案。虽然现在Lucene已经发展到了更高级的版本,但理解3.0的基础对于理解后续...

    Lucene4.4.0

    5. 近实时搜索(Near Realtime Search):4.4.0版本引入了NRT(Near Realtime)特性,允许在不关闭索引的情况下实现快速的更新和搜索。 三、Lucene 4.4.0主要改进 1. 分词和分析器优化:4.4.0版本对分词器进行了...

    lucene的排序过滤和分页.zip

    在搜索引擎和信息检索系统中,Lucene是一个非常关键的开源全文搜索引擎库,它为开发者提供了在Java应用程序中实现全文搜索功能的能力。本资料主要探讨了Lucene中的排序、过滤和分页技术,这些都是构建高效、实用的...

    lucene笔记共38页.pdf.zip

    1. 分布式搜索:通过Solr或Elasticsearch实现分布式索引和搜索,提升性能和可扩展性。 2. 建立多索引:根据需求对不同类型的文档使用不同的分析器和索引策略。 3. 索引缓存:提高搜索速度,如使用BitSet缓存匹配文档...

    LuceneInAction源码

    Lucene是一个高性能、全文检索库,广泛应用于各种搜索引擎和信息检索系统。在这里,我们将深入探讨Lucene的核心概念,以及如何通过源码学习LuceneInAction中的实践技巧。 1. **全文检索基础**: Lucene的核心功能...

Global site tag (gtag.js) - Google Analytics